# -*- coding: utf-8 -*-
"""
Schema验证器
"""

from typing import Any, Dict, List, Tuple
from pathlib import Path


class SchemaValidator:
    """场景数据Schema验证器"""

    def __init__(self, strict: bool = True):
        """
        初始化验证器

        Args:
            strict: 是否严格模式
        """
        self.strict = strict
        self.errors: List[str] = []

    def validate(self, data: Dict[str, Any]) -> Tuple[bool, List[str]]:
        """
        验证场景数据

        Args:
            data: 要验证的数据

        Returns:
            (是否有效, 错误列表)
        """
        self.errors = []

        # 验证顶层结构
        self._validate_top_level(data)

        # 验证meta
        if "meta" in data:
            self._validate_meta(data["meta"])

        # 验证scenes
        if "scenes" in data:
            self._validate_scenes(data["scenes"])
        else:
            self.errors.append("Missing 'scenes' field")

        return len(self.errors) == 0, self.errors

    def _validate_top_level(self, data: Dict[str, Any]) -> None:
        """验证顶层结构"""
        if "version" not in data:
            self.errors.append("Missing 'version' field")

    def _validate_meta(self, meta: Dict[str, Any]) -> None:
        """验证meta字段"""
        # title
        if "title" in meta and not isinstance(meta["title"], str):
            self.errors.append("'meta.title' must be string")

        # language
        if "language" in meta and not isinstance(meta["language"], str):
            self.errors.append("'meta.language' must be string")

    def _validate_scenes(self, scenes: Any) -> None:
        """验证scenes数组"""
        if not isinstance(scenes, list):
            self.errors.append("'scenes' must be a list")
            return

        if len(scenes) == 0:
            self.errors.append("'scenes' cannot be empty")
            return

        for i, scene in enumerate(scenes):
            if not isinstance(scene, dict):
                self.errors.append(f"scene[{i}] must be an object")
                continue
            self._validate_scene(scene, i)

    def _validate_scene(self, scene: Dict[str, Any], index: int) -> None:
        """验证单个场景"""
        prefix = f"scene[{index}]"

        # id
        if "id" in scene and not isinstance(scene["id"], str):
            self.errors.append(f"{prefix}.id must be string")

        # title
        if "title" in scene and not isinstance(scene["title"], str):
            self.errors.append(f"{prefix}.title must be string")

        # narration
        if "narration" in scene:
            if not isinstance(scene["narration"], str):
                self.errors.append(f"{prefix}.narration must be string")
        else:
            self.errors.append(f"{prefix} missing 'narration' field")


def validate_scenes_json(data: Dict[str, Any], strict: bool = True) -> Tuple[bool, List[str]]:
    """
    验证场景JSON数据

    Args:
        data: 要验证的数据
        strict: 是否严格模式

    Returns:
        (是否有效, 错误列表)
    """
    validator = SchemaValidator(strict=strict)
    return validator.validate(data)


def validate_scenes_file(file_path: Path, strict: bool = True) -> Tuple[bool, List[str]]:
    """
    验证场景JSON文件

    Args:
        file_path: 文件路径
        strict: 是否严格模式

    Returns:
        (是否有效, 错误列表)
    """
    if not file_path.exists():
        return False, [f"File not found: {file_path}"]

    try:
        with open(file_path, "r", encoding="utf-8") as f:
            data = json.load(f)
    except json.JSONDecodeError as e:
        return False, [f"JSON parse error: {e}"]
    except Exception as e:
        return False, [f"File read error: {e}"]

    return validate_scenes_json(data, strict=strict)
